package com.applcn.core.config;

import com.applcn.core.filter.ShutdownFilter;
import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * mf.code.order.common.config
 * Description:
 *
 * @author gel
 * @date 2019-06-05 16:54
 */
@Configuration
public class GracefulShutdownConfig {

    /**
     * 停止进程密钥
     */
    private static final String token = "shutdownByToken20200114";

    /**
     * 注册优雅停机Filter
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean<Filter> shutdownFilterRegistrationBean() {
        FilterRegistrationBean<Filter> filterReg = new FilterRegistrationBean<>();
        filterReg.setFilter(new ShutdownFilter());
        filterReg.setDispatcherTypes(DispatcherType.REQUEST);
        filterReg.addInitParameter("token", token);
        filterReg.addUrlPatterns("/shutdown");
        //过滤器顺序
        filterReg.setOrder(0);
        return filterReg;
    }

    /**
     * 用于接受shutdown事件
     *
     * @return GracefulShutdown
     */
    @Bean
    public GracefulShutdown gracefulShutdown() {
        return new GracefulShutdown();
    }

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addConnectorCustomizers(gracefulShutdown());
        return tomcat;
    }

    private class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
        private volatile Connector connector;
        private final int waitTime = 10;

        @Override
        public void customize(Connector connector) {
            this.connector = connector;
        }

        @Override
        public void onApplicationEvent(ContextClosedEvent event) {
            this.connector.pause();
            Executor executor = this.connector.getProtocolHandler().getExecutor();
            if (executor instanceof ThreadPoolExecutor) {
                try {
                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                    System.out.println("shutdown start");
                    threadPoolExecutor.shutdown();
                    System.out.println("shutdown end");
                    if (!threadPoolExecutor.awaitTermination(waitTime, TimeUnit.SECONDS)) {
                        System.err.println("Tomcat 进程在" + waitTime + "秒内无法结束，尝试强制结束");
                    }
                    System.out.println("shutdown success");
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}
